package com.example.chat03.config;

import com.example.chat03.service.ChatService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.io.IOException;

@Slf4j
@Configuration
public class RabbitConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {

    /**
     * 绑定键
     */
    public static final String MSG_TOPIC_KEY = "topic.public";
    /**
     * 队列
     */
    public static final String MSG_TOPIC_QUEUE = "topic.queue";

    public static final String MQ_EXCHANGE = "topic.websocket.exchange";


    private final ChatService chatService;
    private final RabbitTemplate rabbitTemplate;

    public RabbitConfig(ChatService chatService,RabbitTemplate rabbitTemplate) {
        this.chatService = chatService;
        this.rabbitTemplate = rabbitTemplate;
    }

    @PostConstruct
    public void createRabbitTemplate() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    @Bean
    public Queue queue() {
        return new Queue(MSG_TOPIC_QUEUE);
    }


    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(MQ_EXCHANGE);
    }

    @Bean
    public Binding binding(Queue queue, TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(MSG_TOPIC_KEY);
    }

    /**
     * 接受消息的监听，这个监听会接受消息队列topicQueue的消息
     * 针对消费者配置
     */
    @Bean
    public SimpleMessageListenerContainer messageContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
//        container.addQueues(queue());
//        container.setExposeListenerChannel(true);
//        container.setMaxConcurrentConsumers(1);
//        container.setConcurrentConsumers(1);
//        //设置确认模式手工确认
//        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
//        container.setMessageListener(new ChannelAwareMessageListener() {
//            public void onMessage(Message message, com.rabbitmq.client.Channel channel) throws Exception {
//                byte[] body = message.getBody();
//                String msg = new String(body);
//                log.info("rabbitmq收到消息 : " + msg);
//                boolean sendToWebsocket = chatService.sendMsg2(msg);
//
//                if (sendToWebsocket) {
//                    log.info("消息处理成功！ 已经推送到websocket！");
//                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
//                }
//            }
//
//        });
        return container;
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        log.info("ConfirmCallback:     " + "相关数据：" + correlationData);
        log.info("ConfirmCallback:     " + "确认情况：" + ack);
        log.info("ConfirmCallback:     " + "原因：" + cause);
    }

    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.info("ReturnCallback:     " + "消息：" + returned.getMessage());
        log.info("ReturnCallback:     " + "回应码：" + returned.getReplyCode());
        log.info("ReturnCallback:     " + "回应信息：" + returned.getReplyText());
        log.info("ReturnCallback:     " + "交换机：" + returned.getExchange());
        log.info("ReturnCallback:     " + "路由键：" + returned.getRoutingKey());
    }
}
